package com.zhongkun.datahome.core.repository;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhongkun.datahome.common.core.domain.entity.SysDictData;
import com.zhongkun.datahome.core.mapper.SysDictDataMapper;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Repository;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @Author: lifengsheng
 * @Date: 2025/4/22 14:39
 * @Desc
 */
@Repository
public class SysDictDataRepository extends ServiceImpl<SysDictDataMapper, SysDictData> {
    public <T> void setLabel(String dictType, List<T> list, Function<T, String> getValue, BiConsumer<T, String> setLabel,
                             boolean sortFlag) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }

        List<SysDictData> sysDictDataList = this.getBaseMapper().selectByType(dictType);
        if (CollectionUtils.isEmpty(sysDictDataList)) {
            return;
        }

        // 设置label
        Map<String, SysDictData> dictDataValueMap = sysDictDataList.stream()
                .collect(Collectors.toMap(SysDictData::getDictValue, Function.identity(), (v1, v2) -> v1));

        list.forEach(item -> {
            String value = getValue.apply(item);
            if (dictDataValueMap.containsKey(value)) {
                setLabel.accept(item, dictDataValueMap.get(value).getDictLabel());
            }
        });

        // 排序
        if (sortFlag) {
            List<String> sortedValueList = sysDictDataList.stream().map(SysDictData::getDictValue).collect(Collectors.toList());
            list.sort(Comparator.comparingInt(item -> sortedValueList.indexOf(getValue.apply(item))));
        }
    }

    public <T> void sortBy(String dictType, List<T> list, Function<T, String> getValue) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }

        List<SysDictData> sysDictDataList = this.getBaseMapper().selectByType(dictType);
        if (CollectionUtils.isEmpty(sysDictDataList)) {
            return;
        }

        // 排序
        List<String> sortedValueList = sysDictDataList.stream().map(SysDictData::getDictValue).collect(Collectors.toList());

        list.sort(getNullLastComparator(sortedValueList, getValue));
    }

    /**
     * 按标签名排序
     *
     * @param dictType dictType
     * @param list list
     * @param getLabel f
     * @param <T> t
     */
    public <T> void sortByLabel(String dictType, List<T> list, Function<T, String> getLabel) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }

        List<SysDictData> sysDictDataList = this.getBaseMapper().selectByType(dictType);
        if (CollectionUtils.isEmpty(sysDictDataList)) {
            return;
        }

        // 排序
        List<String> sortedLabelList = sysDictDataList.stream().map(SysDictData::getDictLabel).collect(Collectors.toList());

        list.sort(getNullLastComparator(sortedLabelList, getLabel));
    }

    /**
     * 不存在则排后边
     *
     * @param sortedList  sortedList
     * @param getValue getValue
     * @return comparator
     * @param <T> t
     */
    private <T> Comparator<T> getNullLastComparator(List<String> sortedList, Function<T, String> getValue) {
        Map<String, Integer> sortedMap = IntStream.range(0, sortedList.size())
                .boxed()
                .collect(Collectors.toMap(sortedList::get, index -> index));

        return (o1, o2) -> {
            String label1 = getValue.apply(o1);
            String label2 = getValue.apply(o2);

            Integer index1 = sortedMap.get(label1);
            Integer index2 = sortedMap.get(label2);

            if (index1 == null && index2 == null) {
                return 0;
            }
            if (index1 == null) {
                return 1;
            }
            if (index2 == null) {
                return -1;
            }
            return index1.compareTo(index2);
        };
    }
}
